#pragma once
#ifndef NETCLIENT_H
#define NETCLIENT_H

#include "../model/data.h"
#include <QHttpServer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QObject>
#include <QProtobufSerializer>
#include <QWebSocket>

// 前置声明解决循环包含问题
namespace model
{
class DataCenter;
}

namespace network
{
class NetClient : public QObject
{
    Q_OBJECT
  private:
    // 定义重要常量
    // 暂时使用本地环回
    const QString HTTP_URL      = "http://127.0.0.1:8000";
    const QString WEBSOCKET_URL = "ws://127.0.0.1:8001/ws";

  public:
    explicit NetClient(model::DataCenter *dataCenter);

    void initWebsocket();

    void ping();

    void sendAuth();

    QString makeRequestId();

    QNetworkReply *sendHttpRequest(const QString &apiPath, const QByteArray &body);

    void getMyself(const QString &loginSessionId);
    void getFriendList(const QString &loginSessionId);
    void getChatSessionList(const QString &loginSessionId);
    void getApplyList(const QString &loginSessionId);
    void getRecentMessageList(const QString &loginSessionId, const QString &chatSessionId, bool updateUI);

    void sendMessage(const QString &loginSessionId, const QString &chatSessionId, model::MessageType messageType,
                     const QByteArray &content, const QString &extraInfo);

    void handleWsResponse(MicroIMS::NotifyMessage &notifyMessage);
    void handleWsMessage(const model::Message &message);
    void handleWsRemoveFriend(const QString &userId);
    void handleWsAddFriendApply(const model::UserInfo &userInfo);

    void receiveMessage(const QString &chatSessionId);

    void changeNickname(const QString &loginSessionId, const QString &nickname);

    void changeDescription(const QString &loginSessionId, const QString &desc);

    void getVerifyCode(const QString &phone);

    void changePhone(const QString &loginSessionId, const QString &phone, const QString &verifyCodeId,
                     const QString &verifyCode);

    void changeAvatar(const QString &loginSessionId, const QByteArray &avatar);

    void deleteFriend(const QString &loginSessionId, const QString &userId);

    void addFriendApply(const QString &loginSessionId, const QString &userId);

    // 封装响应处理逻辑，包括 HTTP 反序列化 和 业务上的正确性
    template <typename T> std::shared_ptr<T> handleHttpResponse(QNetworkReply *httpResp, bool *ok, QString *reason)
    {
        // 1. 判定 HTTP 层面上是否出错
        if (httpResp->error() != QNetworkReply::NoError)
        {
            *ok     = false;
            *reason = httpResp->errorString();
            httpResp->deleteLater();
            return std::shared_ptr<T>();
        }

        // 2. 获取到响应的 body
        QByteArray respBody = httpResp->readAll();

        // 3. 针对 body 反序列化
        std::shared_ptr<T> respObj = std::make_shared<T>();
        respObj->deserialize(&_serializer, respBody);

        // 4. 判定业务上的结果是否正确
        if (!respObj->success())
        {
            *ok     = false;
            *reason = respObj->errmsg();
            httpResp->deleteLater();
            return std::shared_ptr<T>();
        }

        // 5. 释放 httpResp 对象
        httpResp->deleteLater();
        *ok = true;
        return respObj;
    }

  private:
    model::DataCenter *_dataCenter;

    // http 客户端
    QNetworkAccessManager _httpClient;

    // websocket 客户端
    QWebSocket _webSocketClient;

    // protobuf 序列化器
    QProtobufSerializer _serializer;
  signals:
};
} // namespace network
#endif // NETCLIENT_
